package system_log

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/olivere/elastic/v7"
	"github.com/zeromicro/go-zero/core/logx"
	"gozero-demo/internal/repo/es/es_constants"
	"gozero-demo/internal/svc"
	"gozero-demo/internal/utils"
	"time"
)

type SystemLogESRepository struct {
	logx.Logger
	ctx      context.Context
	esClient *elastic.Client
}

func NewSystemLogESRepository(ctx context.Context, svcCtx *svc.ServiceContext) *SystemLogESRepository {
	return &SystemLogESRepository{
		Logger:   logx.WithContext(ctx),
		ctx:      ctx,
		esClient: svcCtx.ES,
	}
}

// ES存储的数据结构
type SystemLogEsData struct {
	MenuId          int64  `json:"menu_id"`
	Url             string `json:"url"`
	Content         string `json:"content"`
	UserId          int64  `json:"user_id"`
	CreateTime      string `json:"create_time"`
	CreateTimeStamp int64  `json:"create_time_stamp"`
}

// 查询ES的请求参数
type SystemLogEsSearchParams struct {
	SystemLogEsData
	CreateTimeStart string `json:"create_time_start"`
	CreateTimeEnd   string `json:"create_time_end"`
	Page            int    `json:"page"`
	PageSize        int    `json:"page_size"`
}

// 添加ES数据
func (r *SystemLogESRepository) InsertEsData(doc *SystemLogEsData) (*elastic.IndexResponse, error) {
	fmt.Println("doc:", utils.EchoJson(doc))
	resp, err := r.esClient.Index().
		//Index(es_constants.EsIndexSystemLog).
		//Index(es_constants.EsIndexSystemLogV2).
		Index(es_constants.EsIndexSystemLogV3).
		BodyJson(doc).
		Do(r.ctx)
	if err != nil {
		logx.WithContext(r.ctx).Errorf("insert error:%+v", err.Error())
		return nil, err
	}
	fmt.Println("resp:", resp)
	return resp, nil
}

// 查询ES数据
func (r *SystemLogESRepository) SelectEsData(req *SystemLogEsSearchParams) ([]SystemLogEsData, int64, error) {
	boolQuery := elastic.NewBoolQuery()

	// 精确匹配条件
	if req.MenuId > 0 {
		boolQuery = boolQuery.Must(elastic.NewTermQuery("menu_id", req.MenuId))
	}
	if req.UserId > 0 {
		boolQuery = boolQuery.Must(elastic.NewTermQuery("user_id", req.UserId))
	}

	// 模糊搜索条件
	if req.Url != "" {
		boolQuery = boolQuery.Must(elastic.NewMatchQuery("url", req.Url))
	}
	if req.Content != "" {
		boolQuery = boolQuery.Must(elastic.NewMatchQuery("content", req.Content))
	}

	// 时间范围搜索条件
	if req.CreateTimeStart != "" && req.CreateTimeEnd != "" {
		loc, err := time.LoadLocation("Asia/Shanghai")
		// 将字符串格式的时间转换为时间戳
		startTime, err := time.ParseInLocation("2006-01-02 15:04:05", req.CreateTimeStart, loc)
		if err != nil {
			logx.WithContext(r.ctx).Errorf("Failed to parse start time: %v", err)
			return nil, 0, err
		}
		endTime, err := time.ParseInLocation("2006-01-02 15:04:05", req.CreateTimeEnd, loc)
		if err != nil {
			logx.WithContext(r.ctx).Errorf("Failed to parse end time: %v", err)
			return nil, 0, err
		}
		// 使用时间戳进行范围查询
		boolQuery = boolQuery.Must(elastic.NewRangeQuery("create_time").Gte(startTime.Unix()).Lte(endTime.Unix()))
	}

	// 构建搜索请求
	searchResult, err := r.esClient.Search().
		Index(es_constants.EsIndexSystemLog).
		Query(boolQuery).
		From(int((req.Page-1)*req.PageSize)).
		Size(int(req.PageSize)).
		Sort("create_time", false). // true-正序，false-倒序
		//Sort("id", false). // 根据 id 倒序排序
		Do(r.ctx)
	if err != nil {
		logx.WithContext(r.ctx).Errorf("Failed to search Elasticsearch: %v", err)
		return nil, 0, err
	}

	esDataList := make([]SystemLogEsData, 0)
	for _, hit := range searchResult.Hits.Hits {
		var operateRecord SystemLogEsData
		// 使用 json.Unmarshal 手动解析 Elasticsearch 返回的 JSON 数据
		err := json.Unmarshal(hit.Source, &operateRecord)
		if err != nil {
			logx.WithContext(r.ctx).Errorf("Failed to unmarshal hit to Document: %v, Hit: %s", err, hit.Source)
			continue
		}
		esDataList = append(esDataList, operateRecord)
	}

	if len(esDataList) == 0 {
		logx.WithContext(r.ctx).Infof("No items converted to Document, total hits: %d", searchResult.TotalHits())
	}

	return esDataList, searchResult.TotalHits(), nil
}
